using Consul;
using Microsoft.Extensions.Options;
using System.Net;
using System.Text.Json;
using WebRtcProject.Models.Configuration;

namespace WebRtcProject.Services
{
    /// <summary>
    /// Consul 服务发现和配置管理服务
    /// 提供服务注册、发现、健康检查和配置管理功能
    /// </summary>
    public class ConsulService : IDisposable
    {
        private readonly ILogger<ConsulService> _logger;
        private readonly ConsulOptions _options;
        private readonly IConsulClient _consulClient;
        private readonly string _serviceId;
        private bool _disposed = false;

        public ConsulService(ILogger<ConsulService> logger, IOptions<ConsulOptions> options)
        {
            _logger = logger;
            _options = options.Value;

            // 生成唯一服务ID
            _serviceId = string.IsNullOrEmpty(_options.ServiceRegistration.ServiceId)
                ? $"{_options.ServiceRegistration.ServiceName}-{Environment.MachineName}-{Guid.NewGuid().ToString("N")[..8]}"
                : _options.ServiceRegistration.ServiceId;
            //_serviceId = Guid.NewGuid().ToString("N");
            // 创建Consul客户端
            _consulClient = new ConsulClient(config =>
            {
                config.Address = new Uri($"{_options.Scheme}://{_options.Host}:{_options.Port}");
                if (!string.IsNullOrEmpty(_options.Token))
                {
                    config.Token = _options.Token;
                }
                if (!string.IsNullOrEmpty(_options.Datacenter))
                {
                    config.Datacenter = _options.Datacenter;
                }
            });

            _logger.LogInformation("Consul服务初始化完成 - 服务ID: {ServiceId}", _serviceId);
        }

        /// <summary>
        /// 初始化Consul服务
        /// </summary>
        public async Task InitializeAsync()
        {
            if (!_options.Enabled)
            {
                _logger.LogInformation("Consul服务已禁用");
                return;
            }

            try
            {
                // 测试连接
                await TestConnectionAsync();

                // 注册服务
                if (_options.ServiceRegistration.AutoRegister)
                {
                    await RegisterServiceAsync();
                }

                _logger.LogInformation("Consul服务初始化成功");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Consul服务初始化失败");
                throw;
            }
        }

        /// <summary>
        /// 测试Consul连接
        /// </summary>
        private async Task TestConnectionAsync()
        {
            try
            {
                var result = await _consulClient.Agent.Self();
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    _logger.LogInformation("Consul连接测试成功");
                }
                else
                {
                    throw new Exception($"Consul连接失败 - 状态码: {result.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Consul连接测试失败");
                throw;
            }
        }

        /// <summary>
        /// 注册服务到Consul
        /// </summary>
        public async Task RegisterServiceAsync()
        {
            try
            {
                var registration = new AgentServiceRegistration
                {
                    ID = _serviceId,
                    Name = _options.ServiceRegistration.ServiceName,
                    Address = _options.ServiceRegistration.ServiceHost,
                    Port = _options.ServiceRegistration.ServicePort,
                    Tags = _options.ServiceRegistration.Tags,
                    Meta = _options.ServiceRegistration.Meta
                };

                // 配置健康检查
                if (_options.HealthCheck.Enabled)
                {
                    var healthCheckUrl = $"{(_options.ServiceRegistration.ServicePort == 443 ? "https" : "http")}://{_options.ServiceRegistration.ServiceHost}:{_options.ServiceRegistration.ServicePort}{_options.HealthCheck.CheckUrl}";
                    
                    registration.Check = new AgentServiceCheck
                    {
                        HTTP = healthCheckUrl,
                        Method = _options.HealthCheck.CheckMethod,
                        Interval = _options.HealthCheck.Interval,
                        Timeout = _options.HealthCheck.Timeout,
                        DeregisterCriticalServiceAfter = _options.HealthCheck.DeregisterAfter
                    };

                    //if (_options.HealthCheck.Headers.Any())
                    //{
                    //    registration.Check.Header = _options.HealthCheck.Headers;
                    //}
                }

                var result = await _consulClient.Agent.ServiceRegister(registration);
                
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    _logger.LogInformation("服务注册成功 - 服务ID: {ServiceId}, 名称: {ServiceName}", 
                        _serviceId, _options.ServiceRegistration.ServiceName);
                }
                else
                {
                    throw new Exception($"服务注册失败 - 状态码: {result.StatusCode}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "服务注册失败");
                throw;
            }
        }

        /// <summary>
        /// 注销服务
        /// </summary>
        public async Task DeregisterServiceAsync()
        {
            try
            {
                var result = await _consulClient.Agent.ServiceDeregister(_serviceId);
                
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    _logger.LogInformation("服务注销成功 - 服务ID: {ServiceId}", _serviceId);
                }
                else
                {
                    _logger.LogWarning("服务注销失败 - 状态码: {StatusCode}", result.StatusCode);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "服务注销失败");
            }
        }

        /// <summary>
        /// 发现服务
        /// </summary>
        /// <param name="serviceName">服务名称</param>
        /// <returns>服务实例列表</returns>
        public async Task<List<ServiceInstance>> DiscoverServicesAsync(string serviceName)
        {
            try
            {
                var result = await _consulClient.Health.Service(serviceName, "", _options.ServiceDiscovery.OnlyHealthyServices);
                
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    var services = result.Response.Select(entry => new ServiceInstance
                    {
                        ServiceId = entry.Service.ID,
                        ServiceName = entry.Service.Service,
                        Address = entry.Service.Address,
                        Port = entry.Service.Port,
                        Tags = entry.Service.Tags?.ToArray() ?? Array.Empty<string>(),
                        Meta = (Dictionary<string, string>)entry.Service.Meta ?? new Dictionary<string, string>(),
                        HealthStatus = entry.Checks.All(check => check.Status == HealthStatus.Passing) ? "健康" : "不健康"
                    }).ToList();

                    _logger.LogDebug("发现服务 {ServiceName}: {Count} 个实例", serviceName, services.Count);
                    return services;
                }
                else
                {
                    _logger.LogWarning("服务发现失败 - 服务: {ServiceName}, 状态码: {StatusCode}", serviceName, result.StatusCode);
                    return new List<ServiceInstance>();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "服务发现异常 - 服务: {ServiceName}", serviceName);
                return new List<ServiceInstance>();
            }
        }

        /// <summary>
        /// 获取配置值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <returns>配置值</returns>
        public async Task<string?> GetConfigValueAsync(string key)
        {
            try
            {
                var fullKey = $"{_options.Configuration.KeyPrefix}/{key}".TrimStart('/');
                var result = await _consulClient.KV.Get(fullKey);
                
                if (result.StatusCode == HttpStatusCode.OK && result.Response != null)
                {
                    var value = System.Text.Encoding.UTF8.GetString(result.Response.Value);
                    _logger.LogDebug("获取配置成功 - 键: {Key}, 值: {Value}", key, value);
                    return value;
                }
                else
                {
                    _logger.LogDebug("配置不存在 - 键: {Key}", key);
                    return null;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取配置失败 - 键: {Key}", key);
                return null;
            }
        }

        /// <summary>
        /// 设置配置值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="value">配置值</param>
        public async Task<bool> SetConfigValueAsync(string key, string value)
        {
            try
            {
                var fullKey = $"{_options.Configuration.KeyPrefix}/{key}".TrimStart('/');
                var kvPair = new KVPair(fullKey)
                {
                    Value = System.Text.Encoding.UTF8.GetBytes(value)
                };

                var result = await _consulClient.KV.Put(kvPair);
                
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    _logger.LogInformation("设置配置成功 - 键: {Key}", key);
                    return true;
                }
                else
                {
                    _logger.LogWarning("设置配置失败 - 键: {Key}, 状态码: {StatusCode}", key, result.StatusCode);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "设置配置异常 - 键: {Key}", key);
                return false;
            }
        }

        /// <summary>
        /// 获取所有已注册的服务
        /// </summary>
        public async Task<List<string>> GetAllServicesAsync()
        {
            try
            {
                var result = await _consulClient.Catalog.Services();
                
                if (result.StatusCode == HttpStatusCode.OK)
                {
                    var services = result.Response.Keys.ToList();
                    _logger.LogDebug("获取服务列表成功 - 共 {Count} 个服务", services.Count);
                    return services;
                }
                else
                {
                    _logger.LogWarning("获取服务列表失败 - 状态码: {StatusCode}", result.StatusCode);
                    return new List<string>();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取服务列表异常");
                return new List<string>();
            }
        }

        /// <summary>
        /// 获取服务状态信息
        /// </summary>
        public async Task<object> GetServiceStatusAsync()
        {
            try
            {
                var allServices = await GetAllServicesAsync();
                var watchedServices = new Dictionary<string, List<ServiceInstance>>();

                foreach (var serviceName in _options.ServiceDiscovery.WatchedServices)
                {
                    var instances = await DiscoverServicesAsync(serviceName);
                    watchedServices[serviceName] = instances;
                }

                return new
                {
                    ServiceId = _serviceId,
                    ServiceName = _options.ServiceRegistration.ServiceName,
                    ConsulAddress = $"{_options.Scheme}://{_options.Host}:{_options.Port}",
                    RegisteredServices = allServices.Count,
                    WatchedServices = watchedServices,
                    LastUpdated = DateTime.UtcNow
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取服务状态失败");
                return new { Error = ex.Message };
            }
        }

        /// <summary>
        /// 检查Consul连接状态
        /// </summary>
        public async Task<bool> IsHealthyAsync()
        {
            try
            {
                var result = await _consulClient.Agent.Self();
                return result.StatusCode == HttpStatusCode.OK;
            }
            catch
            {
                return false;
            }
        }

        public void Dispose()
        {
            if (_disposed) return;

            try
            {
                if (_options.ServiceRegistration.AutoDeregister && _consulClient != null)
                {
                    try
                    {
                        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                        DeregisterServiceAsync().Wait(cts.Token);
                    }
                    catch (OperationCanceledException)
                    {
                        _logger.LogWarning("服务注销超时");
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "服务注销失败");
                    }
                }

                _consulClient?.Dispose();
                
                _logger.LogInformation("Consul服务已释放");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "释放Consul服务时发生错误");
            }
            finally
            {
                _disposed = true;
            }
        }
    }

    /// <summary>
    /// 服务实例信息
    /// </summary>
    public class ServiceInstance
    {
        public string ServiceId { get; set; } = string.Empty;
        public string ServiceName { get; set; } = string.Empty;
        public string Address { get; set; } = string.Empty;
        public int Port { get; set; }
        public string[] Tags { get; set; } = Array.Empty<string>();
        public Dictionary<string, string> Meta { get; set; } = new();
        public string HealthStatus { get; set; } = string.Empty;
    }
}
